/**
 * Copyright (c) 2018-2028, DreamLu 卢春梦 (qq596392912@gmail.com).
 * <p>
 * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.gnu.org/licenses/lgpl.html
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.dromara.common.web.utils;

import cn.hutool.core.date.format.FastDateFormat;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAccessor;
import java.util.Calendar;
import java.util.Date;

/**
 * DateTime 工具类
 *
 * @author L.cm
 */
public class DateTimeUtil {

    public static final String PATTERN_DATETIME = "yyyy-MM-dd HH:mm:ss";
    public static final String PATTERN_DATE = "yyyy-MM-dd";
    public static final String PATTERN_TIME = "HH:mm:ss";

    public static final DateTimeFormatter DATETIME_FORMAT = DateTimeFormatter.ofPattern(PATTERN_DATETIME);
    public static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern(PATTERN_DATE);
    public static final DateTimeFormatter TIME_FORMAT = DateTimeFormatter.ofPattern(PATTERN_TIME);

    /**
     * 日期时间格式化
     *
     * @param temporal 时间
     * @return 格式化后的时间
     */
    public static String formatDateTime(TemporalAccessor temporal) {
        return DATETIME_FORMAT.format(temporal);
    }

    /**
     * 日期时间格式化
     *
     * @param temporal 时间
     * @return 格式化后的时间
     */
    public static String formatDate(TemporalAccessor temporal) {
        return DATE_FORMAT.format(temporal);
    }

    /**
     * 时间格式化
     *
     * @param temporal 时间
     * @return 格式化后的时间
     */
    public static String formatTime(TemporalAccessor temporal) {
        return TIME_FORMAT.format(temporal);
    }

    /**
     * 日期格式化
     *
     * @param temporal 时间
     * @param pattern  表达式
     * @return 格式化后的时间
     */
    public static String format(TemporalAccessor temporal, String pattern) {
        return DateTimeFormatter.ofPattern(pattern).format(temporal);
    }

    /**
     * 将字符串转换为时间
     *
     * @param dateStr 时间字符串
     * @param pattern 表达式
     * @return 时间
     */
    public static TemporalAccessor parse(String dateStr, String pattern) {
        DateTimeFormatter format = DateTimeFormatter.ofPattern(pattern);
        return format.parse(dateStr);
    }

    /**
     * 将字符串转换为时间
     *
     * @param dateStr   时间字符串
     * @param formatter DateTimeFormatter
     * @return 时间
     */
    public static TemporalAccessor parse(String dateStr, DateTimeFormatter formatter) {
        return formatter.parse(dateStr);
    }

    /**
     * 时间转 Instant
     *
     * @param dateTime 时间
     * @return Instant
     */
    public static Instant toInstant(LocalDateTime dateTime) {
        return dateTime.atZone(ZoneId.systemDefault()).toInstant();
    }

    /**
     * Instant 转 时间
     *
     * @param instant Instant
     * @return Instant
     */
    public static LocalDateTime toDateTime(Instant instant) {
        return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
    }

    public static final FastDateFormat[] FORMATS = {
        FastDateFormat.getInstance("yyyy/MM/dd HH:mm:ss"),
        FastDateFormat.getInstance("yyyy/MM/dd HH:mm"),
        FastDateFormat.getInstance("yyyy/MM/dd HH"),
        FastDateFormat.getInstance("yyyy/MM/dd"),
        FastDateFormat.getInstance("yy/MM/dd HH:mm:ss"),
        FastDateFormat.getInstance("yy/MM/dd HH:mm"),
        FastDateFormat.getInstance("yy/MM/dd HH"),
        FastDateFormat.getInstance("yy/MM/dd"),
        FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss"),
        FastDateFormat.getInstance("yyyy-MM-dd HH:mm"),
        FastDateFormat.getInstance("yyyy-MM-dd HH"),
        FastDateFormat.getInstance("yyyy-MM-dd"),
        FastDateFormat.getInstance("yyyy-M-d H:m:s"),
        FastDateFormat.getInstance("yyyy-M-d H:m"),
        FastDateFormat.getInstance("yyyy-M-d H"),
        FastDateFormat.getInstance("yyyy-M-d"),
        FastDateFormat.getInstance("yy-MM-dd HH:mm:ss"),
        FastDateFormat.getInstance("yy-MM-dd HH:mm"),
        FastDateFormat.getInstance("yy-MM-dd HH"),
        FastDateFormat.getInstance("yy-MM-dd"),
        FastDateFormat.getInstance("yy-M-d H:m:s"),
        FastDateFormat.getInstance("yy-M-d H:m"),
        FastDateFormat.getInstance("yy-M-d H"),
        FastDateFormat.getInstance("yy-M-d"),
        FastDateFormat.getInstance("yyyy年MM月dd日HH时mm分ss秒"),
        FastDateFormat.getInstance("yyyy年MM月dd日HH时mm分"),
        FastDateFormat.getInstance("yyyy年MM月dd日"),
        FastDateFormat.getInstance("yyyy年M月d日H时m分s秒"),
        FastDateFormat.getInstance("yyyy年M月d日H时m分"),
        FastDateFormat.getInstance("yyyy年M月d日"),
        FastDateFormat.getInstance("yy年MM月dd日HH时mm分ss秒"),
        FastDateFormat.getInstance("yy年MM月dd日HH时mm分"),
        FastDateFormat.getInstance("yy年MM月dd日"),
        FastDateFormat.getInstance("yy年M月d日H时m分s秒"),
        FastDateFormat.getInstance("yy年M月d日H时m分"),
        FastDateFormat.getInstance("yy年M月d日"),
        FastDateFormat.getInstance("yyyyMMddHHmmssSSS"),
        FastDateFormat.getInstance("yyyyMMddHHmmss"),
        FastDateFormat.getInstance("yyyyMMddHHmm"),
        FastDateFormat.getInstance("yyyyMMdd"),
        FastDateFormat.getInstance("yyMMddHHmmssSSS"),
        FastDateFormat.getInstance("yyMMddHHmmss"),
        FastDateFormat.getInstance("yyMMddHHmm"),
        FastDateFormat.getInstance("yyMMdd")
    };

    // 字符串转化为日期
    public static Date convertDate(String s) {
        if (org.springframework.util.StringUtils.isEmpty(s)) {
            return null;
        }
        Date ret;
        for (FastDateFormat format : FORMATS) {
            try {
                ret = format.parse(s);

                Calendar calendar = Calendar.getInstance();
                calendar.setTime(ret);
                return calendar.getTime();
            } catch (Exception e) {
                // ignore date parsing error
            }
        }

        return null;
    }
}
